在上個禮拜裡,我們介紹了一些很常見的 feature,我們接下來看看如何在 OpenType 裡實現他們。
用來標記 feature 的「語言」其實並沒有統一的規定,如 Adobe 開發的 AFKDO(Adobe Font Development Kit for OpenType)、Microsoft 的 VOLT (Visual OpenType Layout Tool) 等等。
在這裡,我們會介紹最通用的 AFKDO 語言。
額外注意的是,AFKDO 僅僅是一種標記用的語言,跟 HTML 類似,他本身僅僅用來描述,並沒有辦法進行複雜的邏輯判斷。
A
到 Z
、數字、英文句點(.
)、以及底線(_
)命名。uniXXXX
開頭,而輔助平面上的(五位數的 Unicode)則為 uXXXXX
。$
可以是 uni0024
,也可以是 dollar
;Ω
可以是 uni03A9
,也可以是 Omega
;あ
可以是 uni3042
,也可以是 a-hira
。
<parent>.<child>
來表示同字母的父子關係,例如 A.sc
就是和 A
有關。<alphabet>-<script>
則用來表示同一種文字系統,例如「ㄅ
(b-bopomofo
)、ㄆ
(p-bopomofo
)」;「あ
(a-hira
)、さ
(sa-hira
)」;「Д
(De-cy
)、Ж
(Zhe-cy
)」,看得出來是同一家人。.notdef
字符之外,字元名稱不能以 ,
和 -
開頭。
a
、Kappa
、space
、dollar
、uni60C5
、twodots
、j.full
、m_hungarumlautcomb
都是可用的字符名稱2dots
、.uni597D
、._.A
則無法使用[ ... ]
的方式將數個字符名稱包在其中,用空格分開,使其視為同一類別
space [endash emdash figuredash] space
space endash space
且 space emdash space
且 space figuredash space
-
字符取得一定的範圍
[<firstGlyph> - <lastGlyph>]
[A.swash - Z.swash]
或 [a - z]
或 [0 - 9]
@<name> = [ ... ]
@dash = [endash emdash figuredash];
進行 assignspace @dash space
@Vowels.lc = [a e i o u];
@Vowels.uc = [A E I O U];
@Vowels = [@Vowels.lc @Vowels.uc];
# 等價於
@Vowels = [a e i o u A E I O U];
feature <name> [useExtension] {
# rules...
} <name>;
其中,<name>
為 feature 的名字。長度恆為四個字母,必須要和 OpenType 規格的定義相同,否則無法被軟體正確的讀取與啟用。當該區塊的規則超過 64 KB 時,可以透過 [useExtension]
語法拓展要寫入的規則。每行最後應該使用分號 ;
表示結尾。
例如以下是一個把 ff 處理成 f_f 連字的特性規則:
feature liga {
sub f f by f_f;
} liga;
feature <name> {
…
} <name>;
等價於
feature <name> {
lookup <label> {
…
} <label>;
} <name>;
這樣的好處,在於可以透過 label
更清楚標示我們要替換的規則,例如下方的 pnum 特性包裝了用於拉丁字母的 pnum_latin
跟阿拉伯字母的 pnum_arab
:
feature pnum {
lookup pnum_latin {
sub zero by zero.prop;
sub one by one.prop;
sub two by two.prop;
...
} pnum_latin;
lookup pnum_arab {
sub uni0660 by uni0660.prop;
sub uni0661 by uni0661.prop;
sub uni0662 by uni0662.prop;
...
} pnum_arab;
} sups;
甚至可以在不同的 feature 中引用同一組 lookup 規則,讓版面更好閱讀
lookup myAlternates {
sub A by A.001; # Alternate form
...
} myAlternates;
feature salt { lookup myAlternates; } salt;
feature ss01 { lookup myAlternates; } ss01;
從前面介紹的連字、上下文替代、文體集與字符組成等等,不難發現他們背後的邏輯都是「替換」(lookup)。在 OpenType 裡總共定義了八種替換方式,如下表所示:
Value | Type | 替換規則 |
---|---|---|
1 | Single | 將一個字符換成另一個字符 |
2 | Multiple | 將一個字符換成多個字符 |
3 | Alternate | 將一個字符換成多個可能字符之一 |
4 | Ligature | 將多個字符換成另一個字符 |
5 | Context | 根據前後文替換多個字符 |
6 | Chaining Context | 根據串接的前後文替換多個字符 |
7 | Extension Substitution | 用於擴充 |
8 | Reverse chaining context single | 根據連續前後文反方向替換多個字符(通常用於阿拉伯文) |
對應前幾天我們所介紹的 feature 們:
feature | 中文 | Lookup | 預設 |
---|---|---|---|
liga | 標準連字 | 4 | 預設開啟,但可關閉的連字 |
dlig | 可擇連字 | 4 | 預設不開啟 |
hlig | 歷史連字 | 4 | 預設不開啟 |
smcp | 小寫轉小型大寫字母 | 1 | 預設不開啟 |
c2sc | 大寫轉小型大寫字母 | 1 | 預設不開啟 |
swsh | 花飾字 | 1 | 預設不開啟 |
salt | 預設文體替代字 | 1 | 預設不開啟,通常建議等於ss01 |
ss01-ss20 | 文體集 | 1 | 預設不開啟 |
calt | 上下文替代字 | 6 | 預設開啟 |
vert | 竪排 | 1 | 預設開啟 |
vrt2 | 竪排・改 | 1 | 預設開啟 |
ccmp | 字符分解與組合 | 4, 2 | 強制套用 |
學習完基本語法後,我們會在明天繼續介紹如何編寫